﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Sockets;

namespace PServiceBus.Core.Runtime.Extensions {
    public static class StreamExtension {
        /// <summary>
        /// Retrieved originally from http://www.yoda.arachsys.com/csharp/readbinary.html (10/19/2010)
        /// Modified by TJ Bakre
        /// Reads data from a stream until the end is reached. The
        /// data is returned as a byte array. An IOException is
        /// thrown if any of the underlying IO calls fail.
        /// </summary>
        /// <param name="stream">The stream to read data from</param>
        public static byte[] ToBytes(this Stream stream) {
            var bufferSize = 32768;
            var buffer = new byte[bufferSize];
            var bufferLength = 0;
            int read = 0;
            var ns = stream as NetworkStream;

            int chunk;
            MethodHelper.Try(() =>
            {
                while ((ns == null || (ns != null && ns.DataAvailable)) && (chunk = stream.Read(buffer, read, buffer.Length - read)) > 0) {
                    read += chunk;
                    bufferLength = buffer.Length;
                    // If we've reached the end of our buffer, check to see if there's
                    // any more information
                    if (read == bufferLength) {
                        int nextByte = stream.ReadByte();

                        // End of stream? If so, we're done
                        if (nextByte == -1) break;

                        // Nope. Resize the buffer, put in the byte we've just
                        // read, and continue
                        var newBuffer = new byte[bufferLength * 2];
                        Array.Copy(buffer, newBuffer, bufferLength);
                        newBuffer[read++] = (byte)nextByte;
                        buffer = newBuffer;
                    }
                }
            });
            // Buffer is now too big. Shrink it.
            var ret = new byte[read];
            Array.Copy(buffer, ret, read);
            return ret;
        }
    }
}
